home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d11
/
vmoire14.arc
/
VGAMOIRE.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-04-21
|
84KB
|
2,132 lines
;------ VGAMoire --------------------------------------------------------------
;
; A text mode screen saver which saves the text display and draws a
; pretty, moving graphic design on the screen.
;
; ┌──
; │ moi│re (mwär, môr) n. [Fr, watered silk < MOHAIR] a fabric, esp. silk,
; │ rayon, or acetate, having a watered, or wavy, pattern.
; │ _ _
; │ moi│ré (mwär ra', mô-; môr'a) adj. [Fr, pp. of /moirer/, to
; │ water < /moire/: see prec.] having a watered, or wavy, pattern,
; │ as certain fabrics, stamps, or metal surfaces --n. 1 a watered
; │ pattern pressed into cloth, etc. with engraved rollers 2 MOIRE
; └┬─
; └───────── From Webster's New World Dictionary, Third College Edition,
; Copyright (C) 1988 by Simon & Schuster, Inc.
;
;------ CREDITS ---------------------------------------------------------------
;
; Moire pattern generator for the VGA.
; Written by Christopher Antos, July 1990.
; Copyright (C) 1990 by Christopher Antos.
;
; Inspired by seeing MAGIC for Windows. Also inspired by a lack of
; intelligent, small, pretty screen savers that restored the video and
; mouse states correctly.
;
; Linedraw routines are from "Programmer's Guide to PC & PS/2 Video
; Systems", from Microsoft Press.
;
; If you have any questions or comments, please contact me at:
;
; Christopher Antos
; 2115 Windsor Drive
; Ann Arbor, MI 48103-5652
; (313)663-7912
;
; I'm not too picky about people using this source code. It is not,
; however, public domain. It is copyrighted. If you use this source
; code at all, then you are using the program, and should feel obligated
; to send a donation just as if you were using the program itself. See
; the documentation for more information.
;
;------ COMPILING -------------------------------------------------------------
;
; VGAMoire is written for Turbo Assembler 2.0 and uses "SMART" mode for
; maximum code optimization.
;
; To compile:
;
; tasm /zi vgamoire
; tlink /v /s /l vgamoire
; del vgamoire.obj
; tdstrip -s -c vgamoire
;
; This creates the excutable file, VGAMOIRE.COM; the debugger symbol
; table file, VGAMOIRE.TDS; and the map file, VGAMOIRE.MAP.
;
;------ PLANS FOR REVISION ----------------------------------------------------
;
; - Display new settings when N is used.
; - Possibly some more code compaction.
; - Possibly rearrange routines and only keep large routines (ie,
; character RAM save/restore routines) resident if they will be used.
; - Possibly implement XMS support, if in demand enough.
;
;------ VERSION HISTORY -------------------------------------------------------
;
; v1.0 7/14/90
; ■ Original version.
; ■ Details:
; - Works with monochrome or color VGA cards only.
; VGAMoire will not work on EGA or MCGA, but it
; should work on just about any VGA card. It uses
; the VGA 640x480x16 mode 12h, and uses 15 colors.
; It directly accesses the video DAC color registers
; and reprograms them to display different colors.
; - Will not work in graphics modes. It is highly
; unlikely this will change, though someday, if
; the idea is popular and in demand enough, support
; *may* be added to save the graphics screen to EMS,
; allowing VGAMoire to be able to work even in
; graphics modes (though it still would conflict with
; most games or other "poorly behaved" programs). I
; just don't see the point in it, especially since
; graphical applications are leaning towards
; Microsoft Windows as a standard. Real-mode DOS
; TSRs like VGAMoire would not function, anyhow.
; - Does not beep if it times out in graphics mode, but
; beeps any other time it cannot pop up, including
; if the user hits Ctrl-Alt-Shift while in graphics
; mode.
; - Respects serial (and some parallel) communications,
; and restarts its countdown while any data transfer
; is going on. It will not break carrier when it
; pops up or down (unless the remote host times out).
; - Saves and restores the complete mouse state.
; - Restores the display when mouse movement or a
; keypress is detected. Note that VGAMoire suspends
; the current process. It is NOT a background
; process.
; - With EMS memory installed, VGAMoire can save the
; *entire* video state, including the character
; generator RAM. If this feature is not used, or EMS
; memory is not available, then VGAMoire just saves
; and restores the video mode, page, cursor positions
; (for each of the 8 video pages), and the cursor
; shape. It will reset the screen to 25 lines. No
; video data is lost besides the character generator
; RAM and the screen size.
; NOTE: saving the character generator RAM adds an
; extra 64k to the total EMS memory that VGAMoire
; uses, in order to save all 8 character generator
; RAM banks (at 8k each).
; - VGAMoire should never pop up when it might damage
; the system or cause errors. It monitors a number
; of I/O interrupts and restarts its countdown if any
; I/O is detected. If you need an ABSOLUTE guarantee
; that it will not disrupt the system during a vital
; operation, you can turn it off by pressing
; Ctrl-Alt-E (press Ctrl-Alt-B to turn it on again).
; If you press Ctrl-Alt-Shift to pop VGAMoire up, it
; WILL pop up, even if a vital system operation is in
; progress (eg, disk I/O). Because this can cause
; errors or even crash the system, you should be
; careful about when you pop VGAMoire up manually.
; The only times VGAMoire will not pop up is if the
; display is in a graphics mode or if you are using
; EMS and there is an error while trying to use EMS.
; - Cannot (as yet) detect mouse movement except when
; popped up, so mouse movement will not restart the
; countdown.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; v1.1 8/2/90
; ■ Now deallocates its environment block.
; ■ Can now select how many character generator RAM blocks
; to save, from 1 to 8. Allocates an extra one EMS page
; (16k) per every two character generator RAM blocks that
; are saved, so to save 1 or 2 blocks, it takes 16k of
; EMS; for 3 or 4, it takes 32k; etc.
; ■ At Karen's request, VGAMoire can now mirror the
; pattern in one of four ways: no mirror, horizontally,
; vertically, or both horizontally and vertically.
; ■ Now detects both mouse movement and mouse button
; activity and will reset its countdown. A new option
; has also been added to disable this feature, in case
; a mouse is not present or an old mouse driver causes
; problems with this feature.
; ■ Bug fix: might not have worked correctly before if no
; mouse driver were installed (it might have allocated
; an unpredictably-too-large block of memory).
; ■ Bug fix: when only using conventional memory, the
; keyboard would lock up once a key was pressed to
; return from the moire design. I don't remember quite
; what I did to fix it, although I know I tried a number
; of things.
; ■ Now only keeps one color set resident. When a color
; set is picked, it is copied to the resident copy's
; run-time colorset array (assuming we are changing the
; color set for the resident copy. It does the same
; thing the first time it is installed, except that of
; course it copies the selected color set into the main
; run-time colorset array).
; ■ Frost colors added.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; v1.2 8/7/90
; ■ Bug fix: forgot to use a CS: segment override when
; determining how many font blocks to save/restore, and
; the result was that essentially no fonts were restored.
; VGAMoire now restores fonts correctly.
; ■ Also, to avoid some nasty screen flickering during
; some of the special video accesses, we disable the
; video display while operating on video memory, and
; then reenable it after we're done screwing with video
; memory (only when starting up the moire design or
; returning to text mode).
; ■ Before, we only redefined 15 colors. It occured to me
; that VGAMoire should also reprogram the color
; definition for BLACK, to make sure that the black is
; really black. This is necessary because there are a
; number of programs out that play with the VGA palette,
; and we can't assume that black is really black--we've
; got to MAKE it be black. The whole purpose of VGAMoire
; is to prevent the monitor from burning out! If the
; background were always, oh, say WHITE, then VGAMoire
; wouldn't be much use, now would it? So, anyway, we
; took care of that possibility in this version.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; v1.3 8/14/90
; ■ OOPS! I apologize. I made a stupid error.
; The [N] option didn't work right.
; Sigh. This should now be a solid version, w/o
; version changes for a while. Sigh.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; v1.4 9/4/90
; ■ Improved mouse state saving and restoring. Works
; even with programs making very sophisticated use of
; the mouse driver (for instance, Norton Advanced
; Utilities 5.0).
; ■ New method of reading the keyboard and mouse while
; the screen saver is working. This ensures that
; VGAMoire doesn't receive any "false alerts" and
; refuse to pop up even when it's supposed to.
; ■ VGAMoire will now blank out the screen if a graphics
; mode is active. The moire design will not appear, but
; at least VGAMoire can still function as a screen saver
; even in graphics modes. Special care was taken so that
; THE PROGRAM CAN STILL RUN IN THE BACKGROUND WHILE THE
; SCREEN IS BLANKED OUT. The screen will come back if
; VGAMoire detects any activity--mouse, keyboard, serial
; communications, parallel communications (via int 17h),
; video activity (via int 10h), or disk activity. It
; can be configured to blank the screen in text mode,
; too.
;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; v1.4b 9/21/90
; ■ Source code was reorganized to facilitate future
; support for video cards besides the VGA. Enough
; people indicated an interest that I decided to
; look into adding support for MDA, CGA, MCGA, EGA,
; VGA, Hercules, and InColor cards. Note that this is
; NOT a guarantee for support, just a guarantee I'll
; look into it! Even if I do add support for multiple
; cards, not all of the above cards may be implemented.
; ■ Improved video state save/restore routines mean that
; the entire video state is always saved and restored,
; even if EMS memory is not used. If a non-standard RAM
; font is loaded and active, and the [Fn] option is not
; in effect, then the display will revert to the 8x16
; ROM font. If one of the ROM fonts was being used
; before VGAMoire took over, then that font will be
; restored.
; ** This also remedies a problem with MS Word (or any
; program that used bright background colors) when the
; [E] option was not used. Before, VGAMoire was unable
; restore the bright mode, but now it does.
; ■ Bug fix: I forgot to use a CS: segment override when
; dereferencing the "useEMS" flag when popping up
; VGAMoire. In most situations, this meant VGAMoire
; would nuke any data a program had in the EMS page
; frame (OOPS!). This has been fixed.
;
;------------------------------------------------------------------------------
LOCALS ;allow local labels in procedures (@@xxx)
SMART ;enable maximum code optimization
__DeallocateEnvironment equ 1 ;1=kill env. block, 0=keep env. block so map pgms can ID us
VERSION equ '1.4b' ;current version of VGAMoire
DATE equ 'September 1990' ;date of this version
MaxRev equ 6 ;max times an endpoint direction can reverse before a new random velocity is picked--must be at least 1
MaxLines equ 50 ;maximum number of lines in the moire pattern
cseg segment para public 'CODE'
assume cs:cseg,ds:cseg,ss:nothing,es:nothing
org 100h
main proc near
jmp setup ;go to end of program
main endp
oldmx dw 0 ;old mouse x-coordinate
oldmy dw 0 ;old mouse y-coordinate
mouse db 1 ;flag: 1=check mouse, 0=ignore mouse
delay db 0 ;delay factor
mirror db 0 ;mirror setting
length db 20 ;number of lines in the moire pattern
colorspeed db 1 ;# of lines to draw before changing color
wait dw 0 ;number of int 08h's to wait before popping up
buffersize dw 1000h ;size of video text save buffer
mousesize dw 0800h ;size of mouse state save buffer
fontblocks db 0 ;number of font RAM blocks to save (0=no font saving, 1-8=that many blocks)
onoff db 1 ;onoff: 1=on, 0=off
useEMS db 0 ;useEMS: 1=yes, 0=no
EMShandle dw ? ;our EMS block's handle
counter dw 0 ;count since a key was pressed etc.
videomode db ? ;previous video mode
storetext dw ? ;where to store text (default for conventional memory)
textbuff dw ? ;store address of text buffer
keybuff dw 0 ;keyboard buffer
gonow db 0 ;delay when Ctrl-Alt-Shift is pressed
colorwait db 0 ;countdown to changing color
curcolor db 1 ;color of current line
gfxmode db 0 ;flag: non-zero indicates we are performing a cop-out version of a screen saver because we're in graphics mode
gfxcopout db 0 ;flag: non-zero means always do the cop-out, never draw the moire design
gfxinstalled db 0 ;flag: was this copy of VGAMoire installed with the [Bn] option?
timeout db 1 ;popped up because: 0 if ctrl-alt-shift was hit, 1 if timed out
blackcolor db 0,0,0 ;video DAC color definition for black
colorset label byte ;run-time array holding color set for moire design--color reg values are loaded in at install time, or these defaults are used
db 63, 0, 0 ;color #1 [red]
db 63, 30, 0 ;
db 63, 45, 0 ;
db 63, 63, 0 ; [yellow]
db 42, 63, 0 ;
db 0, 63, 0 ; [green]
db 0, 63, 42 ;
db 0, 63, 63 ; [cyan]
db 0, 45, 63 ;
db 0, 31, 63 ;
db 0, 0, 63 ; [blue]
db 30, 0, 63 ;
db 45, 0, 63 ;
db 63, 0, 63 ; [violet]
db 63, 0, 47 ;color #15
maxcolor db 15 ;highest defined color number
index dw 0 ;index to last line in moire pattern
; current line endpoint data
; data for each coordinate is grouped so loop at [revdir] works w/offsets
xv1 dw ? ;x1 endpoint velocity
x1 dw ? ;endpoint of current line
x1rev db MaxRev ;times endpoint direction has reversed
xv2 dw ? ;x2 endpoint velocity
x2 dw ? ;endpoint of current line
x2rev db MaxRev ;times endpoint direction has reversed
yv1 dw ? ;y1 endpoint velocity
y1 dw ? ;endpoint of current line
y1rev db MaxRev ;times endpoint direction has reversed
yv2 dw ? ;y2 endpoint velocity
y2 dw ? ;endpoint of current line
y2rev db MaxRev ;times endpoint direction has reversed
switchdir dw 0 ;# lines to draw before changing to new random velocities
linesx1 dw MaxLines dup (?) ;arrays holding endpoints of last MaxLines lines
linesy1 dw MaxLines dup (?)
linesx2 dw MaxLines dup (?)
linesy2 dw MaxLines dup (?)
old08h dw ? ;hold addresses of original interrupts
dw ?
old09h dw ?
dw ?
old10h dw ?
dw ?
old13h dw ?
dw ?
;old14h dw ?
dw ?
old17h dw ?
dw ?
int10hOK db 0 ;0 if we should reset [counter] on calls to int 10h -- while our program is running, this is 0ffh (-1)
sax dw ? ;saves ax
sbx dw ? ;saves bx
scx dw ? ;saves cx
sdx dw ? ;saves dx
sdi dw ? ;saves di
ssi dw ? ;saves si
sbp dw ? ;saves bp
ses dw ? ;saves es
sds dw ? ;saves ds
sip dw ? ;saves ip
scs dw ? ;saves cs
sfl dw ? ;saves flags
sax2 dw ? ;saves ax in our08h
sbx2 dw ? ;saves bx in out08h
scx2 dw ? ;saves cx in our08h
sdx2 dw ? ;saves dx in our08h
sds2 dw ? ;saves ds in out08h
reset proc near ;resets countdown, restores screen if in "gfx cop-out" mode
push cs:[wait]
pop cs:[counter]
cmp cs:[gfxmode],0
je @@done
mov cs:[gfxmode],0
xor al,al ;restore screen if gfx cop-out mode was active
call refresh
@@done:
ret
reset endp
our08h proc near ;our int 08h handler
cmp cs:[gonow],0 ;gonow > 0 if Ctrl-Alt-Shift was pressed
jz @@deccnt
dec cs:[gonow] ;subtract 1 from gonow if it is > 0
jg @@deccnt
mov cs:[counter],1 ;if gonow=0 set counter=1 to trigger fireworks
@@deccnt:
dec cs:[counter] ;decrement counter
jz @@moire ;if counter = 0 draw moire pattern
jg @@checkMS
inc cs:[counter] ;if counter was 0 set it 0 again
@@checkMS:
cmp cs:[mouse],0
je @@chain
mov cs:[sds2],ds ;save ds
push cs
pop ds ;set up addressability
mov [sax2],ax ;save ax
mov [sbx2],bx ;save bx
mov [scx2],cx ;save cx
mov [sdx2],dx ;save dx
mov ax,3
xor bx,bx ;in case no mouse driver, zero all regs that would hold return values
xor cx,cx
xor dx,dx
int 33h
cmp bx,0 ;is mouse button pressed
jne @@reset
cmp cx,[oldmx]
jne @@reset
cmp dx,[oldmy]
je @@doneMS
@@reset:
mov [oldmx],cx
mov [oldmy],dx
call reset ;reset countdown
@@doneMS:
mov dx,[sdx2]
mov cx,[scx2]
mov bx,[sbx2]
mov ax,[sax2]
mov ds,[sds2]
@@chain:
jmp DWord Ptr cs:[old08h] ;chain to old int 08h handler
@@moire:
mov cs:[sds],ds ;save ds first, so we can
push cs ; point ds to us to crunch code by
pop ds ; avoiding segment overrides
mov [sax],ax ;save ax
mov [sbx],bx ;save bx
mov [scx],cx ;save cx
mov [sdx],dx ;save dx
mov [sdi],di ;save di
mov [ssi],si ;save si
mov [sbp],bp ;save bp
mov [ses],es ;save es
pop [sip] ;save ip
pop [scs] ;save cs
pop [sfl] ;save flags
push [sfl] ;push flags back on stack
push cs ;push new cs on stack
mov cx,offset runthis ;return to here
push cx ;save offset of runthis
jmp @@chain ;return to do int 8
our08h endp
our09h proc near ;process keyboard interrupt
push ax ;save ax
push es ;save ds
mov es,cs:[keybuff] ;set es = 0
mov al,byte ptr es:[417h] ;get keyboard status byte
pop es
and al,0fh ;mask off top 4 bits
cmp al,12 ;if Ctrl-Alt is pressed
jg @@signal ;if Ctrl-Alt-Shift is pressed
jnz @@chain
in al,60h ;get extended key code
cmp al,18 ;is it Ctrl-Alt-E
jnz @@enable
mov cs:[onoff],0 ;turn off screen saver
@@enable:
cmp al,48 ;is key Ctrl-Alt-B
jnz @@chain
mov cs:[onoff],1 ;turn on screen saver
jmp @@chain
@@signal:
mov cs:[gonow],6 ;delay half a second then invoke screen saver
mov cs:[timeout],0 ;say we're popping up because of user request (ctrl-alt-shift)
@@chain:
call reset ;reset countdown
pop ax ;restore ax
jmp DWord Ptr cs:[old09h] ;chain to old int 09h handler
our09h endp
our10h proc near ;new video interrupt
cmp ax,0caffh ;CA are my initials - check if we're installed
jne @@norm10h
mov bx,cs ;return our PSP
mov ax,0faceh ;return code
iret
@@norm10h:
cmp cs:[int10hOK],0 ;is it us requesting an interrupt
jne @@pass ;if so, don't reset counter, or we'll exit!
call reset ;reset countdown
@@pass:
jmp DWord Ptr cs:[old10h] ;chain to old int 10h handler
our10h endp
our13h proc near ;new disk drive interrupt
call reset ;reset countdown
jmp DWord Ptr cs:[old13h] ;chain to old int 13h handler
our13h endp
;our14h proc near ;new modem interrupt
; call reset ;reset countdown
; jmp DWord Ptr cs:[old14h] ;chain to old int 14h handler
;our14h endp
our17h proc near ;new printer interrupt
call reset ;reset countdown
jmp DWord Ptr cs:[old17h] ;chain to old int 17h handler
our17h endp
;------------------------------------------------------------------------------
;
; CARD-SPECIFIC CODE
;
; any include file used here must declare the following items so it
; can link itself with this VGAMOIRE.ASM module:
;
; SETCOLORS (macro) sets the colors
; STORE (macro) stores the current video state
; SETMODE (macro) sets the graphics mode
; RESTORE (macro) restores the saved video state
; Line10 (proc) draws a line in graphics mode
;
; MinBound equ [minimum endpoint velocity]
; MaxBound equ [maximum endpoint velocity]
;
; MaxX dw [maximum x coordinate]
; MaxY dw [maximum y coordinate]
;
include vga.inc
;
;------------------------------------------------------------------------------
getbuf proc near
cmp cs:[useEMS],0
jz @@done
mov ah,47h ;save page map
mov dx,cs:[EMShandle]
int 67h
or ah,ah
jnz @@error
mov ah,44h ;map our logical pages to physical page frame
mov al,cs:[useEMS] ;al=number of pages we reserved
dec al ;al=number of highest logical page
@@maploop:
push ax
xor bh,bh
mov bl,al ;map logical page to same physical page number
mov dx,cs:[EMShandle]
int 67h
or ah,ah
jnz @@error3 ;@@error3 makes sure to pop ax, too
pop ax
or al,al
jz @@getframe
dec al
jmp @@maploop
@@getframe:
mov ah,41h ;get page frame address
int 67h
or ah,ah
jnz @@error2
mov cs:[storetext],bx
@@done:
clc ;success
ret
@@error3:
pop ax
@@error2:
call freebuf ;uh, oh, better restore page map...
@@error:
stc ;failure
ret
getbuf endp
freebuf proc near
cmp cs:[useEMS],0
jz @@done
mov ah,48h ;restore page map
mov dx,cs:[EMShandle]
int 67h
or ah,ah
@@done:
ret
freebuf endp
rndcnt dw ? ;ceiling of random number range
seed dw ? ;seed for random number generator
aval equ 2743 ;for pseudorandom generator
cval equ 5923 ;for pseudorandom generator
rnum dw rval ;number of times the generator was used
rval equ 200 ;how high rnum can get before getting a new seed and reseting rnum
rnd proc near ;return pseudorandom number in range [0,rndcnt], uses a standard algorithm
push cx
push dx
inc [rnum]
cmp [rnum],rval ;is it time to get a new seed
jl @@getrnd
push es
push bx
xor ax,ax
mov es,ax
mov bx,46ch
push es:[bx] ;read timer
pop [seed] ;store it to seed
mov [rnum],ax
pop bx
pop es
@@getrnd:
mov ax,[seed] ;seed = (seed*aval + cval) mod mval
mov cx,aval
mul cx
add ax,cval
mov [seed],ax
xor dx,dx
mov cx,[rndcnt]
inc cx
or cx,cx
jz @@nomod ;if modulus 65536 (which is effectively mod 0 and thusly divide-by-zero because we're using word values)
div cx
mov ax,dx ;ax in [0,rndcnt]
@@nomod: ;jump point if rndcnt=65535 to avoid divide by zero interrupt
pop dx
pop cx
ret
rnd endp
randvel proc near ;pick a random endpoint velocity
; ARGS: none
; RETS: ax = velocity
mov rndcnt,MaxBound*2 ;random number range [0,MaxBound*2]
@@rv1:
call rnd ;get random number in ax
sub ax,MaxBound ;ax in [-MaxBound,MaxBound]
cmp ax,MinBound
jb @@rv1
cmp ax,-MinBound
ja @@rv1
ret ;return w/ax
randvel endp
getcoords proc near ;load coordinates into regs
cmp [curcolor],0
je @@erase
mov ax,[y2]
mov bx,[x2]
mov cx,[y1]
mov dx,[x1]
ret
@@erase:
mov di,[index] ;get index to last line in moire pattern
shl di,1 ;convert to word index
mov ax,linesy2[di]
mov bx,linesx2[di]
mov cx,linesy1[di]
mov dx,linesx1[di]
ret
getcoords endp
doline proc near ;draw a line from dx,cx to bx,ax
push word ptr [curcolor] ;pass parameters for line to Line10
push ax
push bx
push cx
push dx
call Line10
ret
doline endp
alllines proc near ;draw all lines, including mirroring
call getcoords
call doline ;draw normal first line
test [mirror],1 ;mirror right/left?
jz @@noRL
call getcoords
neg bx
add bx,[MaxX]
neg dx
add dx,[MaxX]
call doline
@@noRL:
test [mirror],2 ;mirror top/bottom?
jz @@noTB
call getcoords
neg ax
add ax,[MaxY]
neg cx
add cx,[MaxY]
call doline
@@noTB:
cmp [mirror],3 ;mirror left/right/top/bottom?
jne @@noBTH
call getcoords
neg ax
add ax,[MaxY]
neg cx
add cx,[MaxY]
neg bx
add bx,[MaxX]
neg dx
add dx,[MaxX]
call doline
@@noBTH:
ret
alllines endp
drawmoire proc near ;draw moire pattern
mov [counter],0 ;zero the counter to avoid "false alerts"
; reset tables holding old line coordinates
push cs
pop es
mov di,offset linesx1
mov cx,MaxLines*4 ;full table size (4 coordinates per line)
mov ax,-1
rep stosw ;set all elements in tables to -1 (word size)
; get random directions, velocities, and coordinates to start the pattern
mov [rndcnt],400
call rnd
add ax,200
mov [switchdir],ax ;store new # of lines to draw before randomly changing endpoint velocities
mov di,(offset xv2 - offset xv1)*4 ;di is offset
randir:
or di,di
jz ranex
sub di,(offset xv2 - offset xv1)
cmp di,(offset xv2 - offset xv1)*2 ;is it doing x or y?
jb dox
mov cx,[MaxY]
jmp doxy
dox:
mov cx,[MaxX]
doxy:
call randvel ;get random endpoint velocity
mov xv1[di],ax ;store it
mov [rndcnt],cx
call rnd ;pick random endpoint coordinate
mov x1[di],ax ;store it
jmp randir
ranex:
di1:
cmp [delay],0 ;if no delay factor requested
jz de1
push cx ;save cx
mov ch,[delay] ;set cx = 100h * delay
xor cl,cl
de0:
cmp [counter],0 ;do this to waste time
cmp [counter],0
loop de0 ;repeat cx times
pop cx ;restore cs
de1:
cmp [counter],0 ;if a key was pressed counter > 0
jng di4
jmp ex1
di4:
; is it time to randomly switch directions yet?
cmp [switchdir],0
jnz @@sdex
mov [rndcnt],400 ;pick new random number of lines to draw before changing velocities
call rnd
add ax,200 ;ax in [200,600]
mov [switchdir],ax ;store new limit
mov di,(offset xv2 - offset xv1)*4 ;di is offset & counter in one
@@sd1:
or di,di
jz @@sdex
sub di,(offset xv2 - offset xv1)
call randvel ;pick a random velocity
mov xv1[di],ax ;ax in [-MaxBound,-MinBound] or [MinBound,MaxBound]
jmp @@sd1
@@sdex:
dec [switchdir]
; reverse directions if hit edges of screen -- loop crunches 4 essentially duplicate blocks of code into one
mov di,(offset xv2 - offset xv1)*4 ;di is offset & counter in one
revdir:
or di,di
jz revex
sub di,(offset xv2 - offset xv1)
mov ax,x1[di]
add ax,xv1[di]
cmp di,(offset xv2 - offset xv1)*2 ;is it checking x or y?
jb checkx
cmp ax,[MaxY]
jmp checkxy
checkx:
cmp ax,[MaxX]
checkxy:
jbe revdir
cmp x1rev[di],0 ;has xv_ reversed directions too many times?
jnz rd1
mov [rndcnt],MaxRev-1 ;pick new random limit for how many times to reverse
call rnd
inc al
mov x1rev[di],al ;store new limit
call randvel ;pick a random velocity
mov bx,xv1[di] ;grab current velocity value
mov bl,ah
and bx,1000000010000000b ;compare signs (directions) of current and new values of velocities
cmp bh,bl
je rb20
neg ax ;if different, make same
rb20:
mov xv1[di],ax ;ax in [-MaxBound,-MinBound] or [MinBound,MaxBound]
rd1:
dec x1rev[di]
neg xv1[di] ;reverse the direction
jmp revdir
revex:
mov di,[index] ;get index into saved line positions
shl di,1 ;convert to word index
mov ax,[x1]
mov linesx1[di],ax ;put x1 into array
mov ax,[x2]
mov linesx2[di],ax ;put x2 into array
mov ax,[y1]
mov linesy1[di],ax ;put y1 into array
mov ax,[y2]
mov linesy2[di],ax ;put y2 into array
; increment index - this gives us the line to erase
inc [index] ;index = index+1
xor ah,ah
mov al,[length]
cmp [index],ax ;is it time to wrap around
jl nw1
xor ax,ax
mov [index],ax ;reset index to 0
nw1:
; get color
cmp [colorwait],0 ;is it time to change color
ja @@samecolor ;if not, jump
mov al,[colorspeed]
mov [colorwait],al
mov al,[maxcolor]
cmp [curcolor],al
jb @@nowrap
mov [curcolor],0 ;wrap around
@@nowrap:
inc [curcolor] ;get next color
@@samecolor:
dec [colorwait] ;get closer to time to change color
mov ax,[yv2]
add [y2],ax ;add yv2 to y2
mov ax,[xv2]
add [x2],ax ;add xv2 to x2
mov ax,[yv1]
add [y1],ax ;add yv1 to y1
mov ax,[xv1]
add [x1],ax ;add xv1 to x1
call alllines ;draw lines, including mirroring
; erase last line(s)
mov di,[index] ;get index to last line in moire pattern
shl di,1 ;convert to word index
cmp linesx1[di],-1 ;is there really a line to erase yet
je di2
push word ptr [curcolor] ;save current color value
mov [curcolor],0 ;color for erasing
call alllines ;clear last line(s) in pattern, including mirroring
pop ax
mov [curcolor],al ;restore current color
di2:
jmp di1 ;next iteration
ex1:
; mov dx,3ceh ;dx = graphics controller port address
; xor ax,ax ;restore set/reset register
; out dx,ax
; inc ax ;restore enable set/reset register
; out dx,ax
; mov al,3 ;data rotate/func select register #
; out dx,ax
; mov ax,0ff08h ;restore bit mask register
; out dx,ax
ret
drawmoire endp
moire proc near
; store text video screen
cmp [gfxcopout],0 ;if gfx cop-out mode is set to "always", then jump to the cop-out routine
jne @@gfxcopout
mov [textbuff],TextBufferSeg+800h ;address of text
mov es,[keybuff] ;set es = 0
mov bl,byte ptr es:[449h] ;get byte at 449h
cmp bl,4 ;what video mode are we in
jl @@go ;if we are in text mode, go!
cmp bl,7 ;are we at mode 7, possibly ega
jz @@mono
@@gfxcopout:
mov al,1 ;in graphics mode, so just blank the screen
call refresh
mov [gfxmode],1 ;set flag that we're doing our graphics mode cop-out version of a screen saver
ret ;return to previous program
@@gofail:
jmp @@fail ;jump point if something goes wrong
@@mono:
mov [textbuff],TextBufferSeg ;set textbuff to b000h if mono
@@go:
mov al,1 ;disable screen refresh (avoid flickering during mode change, etc)
call refresh
call getbuf ;set up EMS page map if using EMS
jc @@gofail ;if we can't
mov ax,2 ;hide pointer, in case it's showing
int 33h
push es
mov ax,16h ;save mouse state
push [storetext] ;get segment of save buffer
pop es
mov dx,[buffersize] ;offset past stored video screen
int 33h
mov ax,21h ;reset the mouse
int 33h
pop es
mov bl,byte ptr es:[449h] ;save video mode
mov [videomode],bl
STORE ;[macro] save current video state
call freebuf ;restore EMS page map (if using EMS)
SETMODE ;[macro] sets the graphics video mode
push cs ;set ds = cs
pop ds
SETCOLORS ;[macro] set new video DAC color registers
xor al,al ;reenable video refresh (the BIOS should have taken care of this when we set the graphics mode, but we do it, too, just in case)
call refresh
call drawmoire ;draw moire pattern
mov al,1 ;disable screen refresh (avoid flickering during mode change, etc)
call refresh
push cs
pop ds
xor ah,ah ;reset to saved mode
mov al,[videomode] ; must do this, even if we're restoring the video state afterwards, otherwise the
int 10h ; mouse driver thinks we're still in gfx mode and the mouse pointer gets mangled.
mov al,1 ;disable screen refresh (avoid flickering during mode change, etc)
call refresh
RESTORE ;[macro] restore saved video state
@@done:
xor al,al ;reenable video refresh
call refresh
push cs
pop ds
call reset ;reset the countdown
ret
@@fail:
cmp [timeout],0 ;if failed but we timed out, don't do anything
jnz @@done
mov ah,0eh
mov al,7 ;cheapie way to sound a bell
xor bx,bx
int 10h
jmp @@done
moire endp
runthis proc near ;run graphics then restore to program
mov ax,cs ;set ds = cs
mov ds,ax
not [int10hOK] ;tell our int 10h handler we're calling it
cmp [onoff],0 ;was VGAMoire turned off
jz @@nope
call moire ;save screen, draw moire pattern, restore screen
@@nope:
mov ax,[sax] ;restore ax
mov bx,[sbx] ;restore bx
mov cx,[scx] ;restore cx
mov dx,[sdx] ;restore dx
mov di,[sdi] ;restore di
mov si,[ssi] ;restore si
mov bp,[sbp] ;restore bp
mov es,[ses] ;restore es
push [sfl] ;put flags on stack
push [scs] ;put cs on stack
push [sip] ;put ip on stack
mov ds,[sds] ;restore ds
not cs:[int10hOK] ;tell our int 10h handler to reset [counter] on int requests
mov cs:[timeout],1 ;reset timeout indicator to say true timeout, not ctrl-alt-shift hit
iret ;return to previous program
runthis endp
align 16 ;paragraph aligned so we can store just a segment address
EndOfResident label byte
_mypsp dw ?
deinstall proc near
; This could be done by simply deallocating our PSP block and environment
; block (if not deallocated at installation), but this is more
; "well-behaved", in that if a DOS extender allocates an extra info block
; per program, this will also deallocate that block, because it simply
; deallocates anything that belongs to us.
; This isn't resident code, so we might as well take the extra effort.
mov ax,0caffh ;are we installed yet
int 10h
cmp ax,0faceh
je @@deinstall
mov ah,9 ;if not, print error message and abort
mov dx,offset nomsg
int 21h
mov ax,4c01h
int 21h
@@deinstall:
mov cs:[_mypsp],bx ;save the PSP of the resident copy
mov es,bx
mov bl,es:[useEMS] ;find out if resident copy is using EMS
mov cs:[useEMS],bl
mov bx,es:[EMShandle] ;get EMS handle resident copy is using
mov cs:[EMShandle],bx
mov ax,3508h ;check if another program covered us
int 21h
mov ax,es
cmp ax,cs:[_mypsp]
jne @@yousureb
cmp bx,offset our08h
jne @@yousureb
mov ax,3509h
int 21h
mov ax,es
cmp ax,cs:[_mypsp]
jne @@yousureb
cmp bx,offset our09h
jne @@yousureb
mov ax,3510h
int 21h
mov ax,es
cmp ax,cs:[_mypsp]
jne @@yousureb
cmp bx,offset our10h
jne @@yousureb
mov ax,3513h
int 21h
mov ax,es
cmp ax,cs:[_mypsp]
jne @@yousureb
cmp bx,offset our13h
jne @@yousureb
; mov ax,3514h
; int 21h
; mov ax,es
; cmp ax,cs:[_mypsp]
; jne @@yousureb
; cmp bx,offset our14h
; jne @@yousureb
mov ax,3517h
int 21h
mov ax,es
cmp ax,cs:[_mypsp]
jne @@yousureb
cmp bx,offset our17h
jne @@yousureb
jmp @@yessure
@@yousureb:
jmp @@yousure
@@yessure:
mov bx,cs:[_mypsp]
mov es,bx
mov dx,word ptr es:[old08h] ; get old 8h vector
mov ds,word ptr es:[old08h+2]
mov ax,2508h ; restore old 8h vector
int 21h
mov dx,word ptr es:[old09h] ; get old 9h vector
mov ds,word ptr es:[old09h+2]
mov ax,2509h ; restore old 9h vector
int 21h
mov dx,word ptr es:[old10h] ; get old 10h vector
mov ds,word ptr es:[old10h+2]
mov ax,2510h ; restore old 10h vector
int 21h
mov dx,word ptr es:[old13h] ; get old 13h vector
mov ds,word ptr es:[old13h+2]
mov ax,2513h ; restore old 13h vector
int 21h
; mov dx,word ptr es:[old14h] ; get old 14h vector
; mov ds,word ptr es:[old14h+2]
; mov ax,2514h ; restore old 14h vector
; int 21h
mov dx,word ptr es:[old17h] ; get old 17h vector
mov ds,word ptr es:[old17h+2]
mov ax,2517h ; restore old 17h vector
int 21h
push cs
pop ds
mov ah,52h
int 21h
mov ax,word ptr es:[bx-2]
mov es,ax
@@looptop:
cmp byte ptr es:[0],4dh
jne @@end
mov ax,word ptr es:[1]
cmp ax,word ptr cs:[_mypsp]
jne @@notourblock
push es
mov ax,es
inc ax
mov es,ax
mov ah,49h
int 21h
pop es
@@notourblock:
mov cx,word ptr es:[3]
inc cx
mov ax,es
add ax,cx
mov es,ax
jmp @@looptop
@@end:
cmp cs:[useEMS],0
jz @@noEMS
mov ah,45h ;release resident copy's EMS block, if present
mov dx,cs:[EMShandle]
int 67h ;if there was an error, it's out of our hands
@@noEMS:
mov ah,9 ;print deinstallation msg
mov dx,offset demsg
int 21h
mov ax,4c00h
int 21h
@@yousure:
mov dx,offset suremsg
call @@str29
@@getch:
mov ah,8
int 21h
cmp al,'y'
je @@dok
cmp al,'Y'
je @@dok
cmp al,'n'
je @@dok
cmp al,'N'
je @@dok
cmp al,27
je @@dok
jmp @@getch
@@dok:
push ax
cmp al,27
je @@nopr
int 29h ;undocumented character output routine
@@nopr:
mov al,13 ;go to next line
int 29h
mov al,10
int 29h
pop ax
cmp al,'y'
je @@yes
cmp al,'Y'
je @@yes
mov dx,offset stilmsg
call @@str29
pop es
pop di
mov ax,4c01h ;exit, return ERRORLEVEL 1
int 21h
@@yes:
jmp @@yessure
@@str29:
mov di,dx
@@sloop: ;output routine emulates int 21h fnc 9h
mov al,cs:[di]
inc di
cmp al,'$'
je @@sexit
int 29h ;undocumented character output routine
jmp @@sloop
@@sexit:
ret
deinstall endp
newopts proc near
push ax
push bx
push dx
mov ax,0caffh ;are we installed yet
int 10h ;returns bx=resident PSP if installed, and ax=0faceh
cmp ax,0faceh
je @@setnew
mov ah,9 ;if not, print error message and abort
mov dx,offset nomsg
int 21h
mov ax,4c01h
int 21h
@@setnew:
mov es,bx ;set up to write subsequent params to resident copy
pop dx
pop bx
pop ax
ret
newopts endp
setminutes proc near
call finddigit ;convert string to digit
jc @@done
cmp cl,30 ;make sure it is less than 30 minutes
ja @@done
mov ax,444h ;multiply digit by 444h
mul cx
mov es:[wait],ax ;save, this is # of int 8's performed in x mins
@@done:
ret
setminutes endp
setdelay proc near
call finddigit ;convert string to digit
jc @@done
mov es:[delay],cl ;save digit as a delay factor
@@done:
ret
setdelay endp
setlines proc near
call finddigit ;get digit
jc @@done
cmp cl,MaxLines ;was number less than MaxLines
ja @@done
mov es:[length],cl ;save number of lines
@@done:
ret
setlines endp
setpages proc near
call finddigit ;get value specified
jc @@done
cmp cl,8 ;if greater than 8 ignore it
ja @@done
mov ax,1000h
xor ch,ch
mul cx ;number of bytes to save = 1000h * cx = ax
mov [buffersize],ax ;save number of bytes to save
@@done:
ret
setpages endp
setEMS proc near
mov cs:[useEMS],1
ret
setEMS endp
setsavfon proc near
call finddigit ;get value specified
jc @@done
cmp cl,8 ;if greater than 8 ignore it
ja @@done
mov cs:[fontblocks],cl
@@done:
ret
setsavfon endp
setvidact proc near
call finddigit ;get value specified
jc @@done
cmp cl,2 ;if greater than 2 ignore it
ja @@done
dec cl
mov es:[int10hOK],cl ;set video activity monitor
@@done:
ret
setvidact endp
setmouse proc near
call finddigit ;get value specified
jc @@done
cmp cl,2 ;if greater than 2 ignore it
ja @@done
dec cl
mov es:[mouse],cl ;set mouse activity monitor
@@done:
ret
setmouse endp
setblank proc near
cmp es:[gfxinstalled],0 ;was VGAMoire installed with the [Bn] option?
jne @@done ;yep, tough luck, can't change it then
call finddigit ;get value specified
jc @@done
cmp cl,2 ;if greater than 2 ignore it
ja @@done
dec cl
mov es:[gfxcopout],cl ;set blank mode (graphics "cop-out" mode)
mov cs:[gfxinstalled],cl ;set [gfxinstalled] to 1 if B2 is used
@@done:
ret
setblank endp
setmirror proc near
call finddigit ;get value specified
jc @@done
cmp cl,4 ;if greater than 4 ignore it
ja @@done
dec cl
mov es:[mirror],cl ;set mirror setting
@@done:
ret
setmirror endp
setspeed proc near
call finddigit ;get value specified
jc @@done
mov es:[colorspeed],cl ;store speed
@@done:
ret
setspeed endp
setcolor proc near
call finddigit ;get value specified
jc @@done
cmp cl,numsets ;if greater than number of color sets we know of, ignore it
ja @@done
push di ;save di & si
push si
mov si,offset rainbow ;get base address of color sets
dec cl ;zero-based for indexing
xor ah,ah
mov al,cl
mov cl,(15*3)+1 ;calc offset from [rainbow] to color set
mul cl
add si,ax ;calc pointer to color set to use
mov cx,(15*3)+1 ;number of colors to copy + maxcolor descriptor
mov di,offset colorset ; es:di -> location of colorset array (where to copy to)
rep movsb ;copy color set from list of color sets into the run-time array
pop si
pop di ;restore di & si
@@done:
ret
setcolor endp
seton proc near
mov es:[onoff],1
ret
seton endp
setoff proc near
mov es:[onoff],0
ret
setoff endp
getEMS proc near
push di
push si
mov ax,3567h ;test for presense of EMS
int 21h ;returns es=segment ptr
mov di,10 ;es:di -> byte at offset 10 in device header
mov si,offset emmname
mov cx,8
cld
repz cmpsb ;compare strings
jz @@EMSthere
mov ah,9 ;print message saying no EMS m.m.
mov dx,offset noEMS
int 21h
jmp @@error
@@EMSthere:
mov ah,46h ;get version, if lower than 3.0, can't use (actually, it might work, but since i'm not sure...)
int 67h
cmp al,30h
jae @@EMS30
mov ah,9 ;print message saying we need at least EMS 3.0
mov dx,offset EMS30
int 21h
jmp @@error
@@EMS30:
mov ah,43h ;allocate an EMS handle to use
mov bx,1
cmp cs:[buffersize],3000h ;three vid pages or less, just one EMS page
jbe @@getpages
inc bx
cmp cs:[buffersize],7000h ;seven or less, two EMS pages
jbe @@getpages
inc bx ;eight vid pages needs three EMS pages
@@getpages:
mov cs:[useEMS],bl ;store number of pages we're allocating for video text save area
cmp cs:[fontblocks],0 ;should we save character RAM also
jz @@nochr
xor dh,dh
mov dl,cs:[fontblocks] ;how many font blocks do we need to save
inc dl ;round up and
shr dl,1 ; convert to EMS pages
add bx,dx ;add in pages for font RAM
@@nochr:
int 67h
or ah,ah
jz @@gotEMS
mov ah,9 ;error allocating EMS, so just use conventional
mov dx,offset EMSerr
int 21h
jmp @@error
@@gotEMS:
mov cs:[EMShandle],dx
mov ah,46h ;get version, if 4.0 or higher, we're going to name our block
int 67h
cmp al,40h
jb @@done
mov ax,5301h ;give our handle a name
mov dx,cs:[EMShandle]
mov si,offset EMSname
int 67h
@@done:
pop si
pop di
ret
@@error:
mov ah,9 ;say we'll use conventional memory instead
mov dx,offset cnvmsg
int 21h
mov cs:[useEMS],0
mov cs:[fontblocks],0 ;can't save fonts anymore!!
jmp @@done
emmname db 'EMMXXXX0'
EMSname db 'VGAMoire'
noEMS db 'EMS memory manager not found.',13,10,'$'
EMS30 db 'VGAMoire requires EMS 3.0 or higher.',13,10,'$'
EMSerr db 'Error allocating EMS memory.',13,10,'$'
cnvmsg db 'Using conventional memory instead.',13,10,'$'
getEMS endp
reznew db 0 ;flag: are we setting new params for resident copy
setup proc near ;main procedure for setting up program
mov ah,9 ;print id string
mov dx,offset msg
int 21h
; process the command line
mov di,80h ;set si and di to command tail
mov si,81h
@@nextchr:
lodsb ;get next character
cmp al,' ' ;is it a whitespace, space or tab or enter
jz @@nextchr
cmp al,9
jz @@nextchr
cmp al,0dh ;if enter quit processing
jz @@endln
dec si ;adjust si
xor al,al ;mark end of string with 0
stosb
@@getchr:
lodsb ;get character
cmp al,' ' ;is it a whitespace
jz @@nextchr
cmp al,9
jz @@nextchr
cmp al,0dh
jz @@endln
cmp al,'a' ;is the character a small letter
jl @@storchr
cmp al,'z'
jg @@storchr
and al,223 ;if so capitalize it
cmp al,'N' ;send new params?
jne @@storchr
mov [reznew],1
@@storchr:
stosb ;store character again
jmp @@getchr
@@endln:
xor ax,ax ;put double zero in tail to mark end of buffer
stosw
cmp [reznew],1 ;should we set options for resident copy?
jne @@parse
call newopts
@@parse:
; parse the command line and act on parameters
mov si,80h ;start reading here
cmp word ptr [si+1],'?' ;was '?' input
jnz @@findnull
mov ah,9 ;then print message describing switches
mov dx,offset usage
int 21h
mov ax,4c00h ;and quit with error level 0
int 21h
@@findnull:
lodsb ;read character until we get a 0
or al,al
jnz @@findnull
cmp byte ptr [si],al ;is next character a 0, are we finished ?
jnz @@continue
jmp @@donepar
@@continue:
lodsb ;get character
xor bp,bp ;compare to valid options
@@nextone:
mov ah,cs:[bp + offset options]
or ah,ah
jz @@findnull
cmp ah,al
je @@gotone
inc bp
jmp @@nextone
@@gotone:
shl bp,1 ;convert to word index
call word ptr cs:[bp + offset optaddr]
jmp @@findnull
@@donepar:
cmp [useEMS],0
jnz @@possiblefont
mov [fontblocks],0
@@possiblefont:
; push cs
; pop es
cmp [reznew],0
jz @@start
; -- possible enhancement: display current settings before exitting
mov ah,9 ;display msg that params have been updated
mov dx,offset newmsg
int 21h
mov ax,4c00h
int 21h
@@start:
; start the moire pattern without going resident
call noresident
cmp [useEMS],0
jz @@noEMS
call getEMS
@@noEMS:
mov ax,0caffh ;are we installed yet
int 10h
cmp ax,0faceh
jne @@storevec
mov ah,9 ;if so, print error message and abort
mov dx,offset ainmsg
int 21h
mov ax,4c01h
int 21h
@@storevec:
; store interrupt vectors
mov ax,3508h ;save int 08h vector
int 21h
mov word ptr [old08h],bx
mov word ptr [old08h+2],es
mov ah,25h ;install our int 08h
mov dx,offset our08h
int 21h
mov ax,3509h ;save int 09h vector
int 21h
mov word ptr [old09h],bx
mov word ptr [old09h+2],es
mov ah,25h ;install our int 09h
mov dx,offset our09h
int 21h
mov ax,3510h ;save int 10h vector
int 21h
mov word ptr [old10h],bx
mov word ptr [old10h+2],es
mov ah,25h ;install our int 10h
mov dx,offset our10h
int 21h
mov ax,3513h ;save int 13h vector
int 21h
mov word ptr [old13h],bx
mov word ptr [old13h+2],es
mov ah,25h ;install our int 13h
mov dx,offset our13h
int 21h
; mov ax,3514h ;save int 14h vector
; int 21h
; mov word ptr [old14h],bx
; mov word ptr [old14h+2],es
; mov ah,25h ;install our int 14h
; mov dx,offset our14h
; int 21h
mov ax,3517h ;save int 17h vector
int 21h
mov word ptr [old17h],bx
mov word ptr [old17h+2],es
mov ah,25h ;install our int 17h
mov dx,offset our17h
int 21h
if __DeallocateEnvironment
mov ax,word ptr ds:[2ch] ; deallocate our environment block
mov es,ax
mov ah,49h
int 21h
endif
mov ah,9 ;print install message
mov dx,offset inmsg
int 21h
; set up and install VGAMoire
push [wait] ;set counter = wait
pop [counter]
xor dx,dx
cmp [useEMS],0
jnz @@yesEMS
mov [storetext],cs ;make pointer to video save area
mov ax,offset EndOfResident
mov cl,4
shr ax,cl
add [storetext],ax ;got new address for conventional memory video save buffer
xor bx,bx ;set bx=0 in case no mouse driver!!!
mov ax,15h ;find size of mouse state buffer
int 33h
mov [mousesize],bx ;store size of mouse buffer
push bx
;+*VGA
mov ax,1c00h ;get size of video state save buffer
mov cx,7
int 10h
mov cl,6 ;multiple by 64
shl bx,cl
mov dx,bx
;-*VGA
pop bx
cmp [gfxcopout],0 ;if gfx cop-out mode is in effect, don't reserve any memory
jne @@yesEMS
add dx,[buffersize] ;plus space to reserve for text buffer
add dx,bx ;and for mouse state buffer
@@yesEMS:
add dx,offset EndOfResident ;actual program code to reserve
inc dx ;for int 27h, dx = (offset last_byte) + 1
int 27h
setup endp
finddigit proc near ;convert string to digit
xor ax,ax ;set ax = 0 = cx, bx = 10
mov bx,10
mov cx,ax
@@nextdigit:
lodsb ;get next character
or al,al ;are we at end
jz @@done
cmp al,'9' ;was character bigger than 9
jg @@fail
sub al,'0' ;or less than zero
jl @@fail
xchg ax,cx ;cx = cx * 10 + ax
mul bx
add cx,ax
or ch,ch ;is cx > 255
jz @@nextdigit
@@fail:
dec si ;return with failure
stc
ret
@@done:
or cx,cx ;is cx = 0 then return failure
jz @@fail
dec si ;return with success
clc
ret
finddigit endp
;memprob db 'Memory allocation error.',13,10,'$'
noresident proc near ;run graphics w/o staying resident
cmp [wait],0 ;was wait time specified
jz nr1
ret ;if so, return and install
nr1:
; mov ah,4ah ;free unneeded memory
; mov bx,sp
; mov cl,4
; shr bx,cl
; inc bx ;extra paragraph
; push cs
; pop es
; int 21h
; jnc @@nonres_ok
; mov ah,9
; mov dx,offset memprob
; int 21h
; mov ax,4c01h
; int 21h
;@@nonres_ok:
mov [buffersize],8000h ;save all video text RAM
cmp [useEMS],0
jz @@noEMS1
call getEMS
@@noEMS1:
mov [wait],444h ;give wait a value so we don't loop endlessly!
mov [counter],444h
cmp [useEMS],0
jnz @@yesEMS
mov [storetext],cs ;make our video save buffer be after all important code
mov ax,offset EndOfNonresident
mov cl,4
shr ax,cl
add [storetext],ax ;got new address for conventional memory video save buffer
@@yesEMS:
mov ax,3509h ;save int 09h vector
int 21h
mov word ptr [old09h],bx
mov word ptr [old09h+2],es
mov ax,2509h ;install our int 09h
mov dx,offset our09h
int 21h
mov ax,3508h ;save int 08h vector
int 21h
mov word ptr [old08h],bx
mov word ptr [old08h+2],es
mov ax,2508h ;install our int 08h
mov dx,offset our08h
int 21h
push es ;timer-based pause loop
mov es,[keybuff]
mov bx,46ch
mov cx,es:[bx] ;read timer
@@tryagain:
mov dx,es:[bx] ;read timer
sub dx,cx ;find difference
test dx,8000h ;negative?
jz @@pos
neg dx ;take absolute value
@@pos:
cmp dx,3 ;wait a smidgen
jb @@tryagain
pop es
mov [timeout],1
mov [counter],1
@@untildone:
cmp [counter],10 ;wait until counter gets reset (ie, mouse or keyboard activity)
jb @@untildone
mov ax,2508h ;restore old int 08h handler
mov dx,word ptr [old08h] ; (don't need to use a CS: override yet)
mov ds,word ptr [old08h+2]
int 21h
mov ax,2509h ;restore old int 09h handler
mov dx,word ptr cs:[old09h] ; (from here on we need CS: overrides)
mov ds,word ptr cs:[old09h+2]
int 21h
push cs ;restore DS: addressability
pop ds
cmp [useEMS],0
jz @@noEMS2
mov ah,45h ;release EMS block, if present
mov dx,[EMShandle]
int 67h ;if there was an error, it's out of our hands
@@noEMS2:
mov ax,4c00h ;exit, errorlevel 0
int 21h
noresident endp
align 16 ;paragraph aligned so we can just store a segment address
EndOfNonresident label byte
options db 'BCDEFLMPRSUVW-+',0
optaddr label word
dw setblank
dw setcolor
dw setdelay
dw setEMS
dw setsavfon
dw setlines
dw setmouse
dw setpages
dw setmirror
dw setspeed
dw deinstall
dw setvidact
dw setminutes
dw setoff
dw seton
msg db 13,10
db 'VGAMoire ',VERSION,', by Christopher Antos, ',DATE,', (C)1990',13,10,'$'
inmsg db '++ VGAMoire now installed.',13,10,'$'
nomsg db '** VGAMoire has not been installed yet.',13,10,'$'
ainmsg db '** VGAMoire is already installed.',13,10
db ' Use VGAMOIRE U to deinstall.',13,10
db ' Use VGAMOIRE N to set new parameters.',13,10,'$'
demsg db '-- VGAMoire now deinstalled.',13,10,'$'
suremsg db 13,10
db 'Another program has captured VGAMoire''s interrupt vectors.',13,10
db 'Deinstalling VGAMoire may cause a system crash.',13,10
db 'Are you sure you want to deinstall VGAMoire? $'
stilmsg db '** VGAMoire is still installed.',13,10,'$'
newmsg db '++ New parameters sent to resident VGAMoire.',13,10,'$'
usage db 13,10
db 'Usage: VGAMOIRE [Bn] [Cn] [Dn] [E] [Fn] [Ln] [Mn] [N]',13,10
db ' [Pn] [Rn] [Sn] [U] [Vn] [Wn] [-] [+]',13,10
db 10
db 'Summary of options: * = invalid if used with [N]',13,10
db ' Bn blank: 1-graphics, 2-always Pn * save <n> video pages (1-8)',13,10
db ' Cn colors: 1-rainbow, 2-fire, Rn mirror: 1-none, 2-H, 3-V, 4-H/V',13,10
db ' 3-frost, 4-pastel Sn color speed: (1-255)',13,10
db ' Dn delay: (1-255) U uninstall',13,10
db ' E * use EMS Vn video: 1-monitor, 2-ignore',13,10
db ' Fn * save <n> font blocks (1-8) Wn wait <n> minutes (1-30)',13,10
db ' Ln lines: (1-50) - turn off',13,10
db ' Mn mouse: 1-monitor, 2-ignore + turn on',13,10
db ' N send options to resident copy ',13,10
db 10
db ' Press Ctrl-Alt-Shift to pop up screen saver. The screen saver may be',13,10
db ' disabled by pressing Ctrl-Alt-E and reenabled by pressing Ctrl-Alt-B.',13,10
db ' Use VGAMOIRE - N to turn off resident copy (or + N to turn back on).',13,10
db '$'
numsets equ 5 ;number of color sets defined
; R,G,B values for video DAC color registers
rainbow db 63, 0, 0 ;color #1 [red]
db 63, 30, 0 ;
db 63, 45, 0 ;
db 63, 63, 0 ; [yellow]
db 42, 63, 0 ;
db 0, 63, 0 ; [green]
db 0, 63, 42 ;
db 0, 63, 63 ; [cyan]
db 0, 45, 63 ;
db 0, 31, 63 ;
db 0, 0, 63 ; [blue]
db 30, 0, 63 ;
db 45, 0, 63 ;
db 63, 0, 63 ; [violet]
db 63, 0, 47 ;color #15
db 15
fire db 63, 0, 0 ;color #1 [red]
db 63, 7, 0
db 63, 13, 0
db 63, 22, 0
db 63, 27, 0
db 63, 32, 0
db 63, 36, 0
db 63, 42, 0
db 63, 48, 0
db 63, 52, 0
db 63, 58, 0
db 63, 63, 0 ;color #13 [yellow]
db 63, 49, 0
db 63, 40, 0
db 63, 30, 0
db 15
frost db 63, 21, 63 ;color #1 [purple]
db 52, 21, 63
db 42, 21, 63
db 31, 21, 63
db 21, 21, 63 ;color #5 [blue]
db 21, 29, 63
db 21, 38, 63
db 21, 46, 63
db 21, 54, 63
db 21, 63, 63 ;color #10 [cyan]
db 35, 63, 63
db 49, 63, 63
db 63, 63, 63 ;color #13 [white]
db 63, 49, 63
db 63, 35, 63
db 15
pastel db 63, 47, 47 ;color #1 [red]
db 63, 50, 47 ;
db 63, 54, 47 ;
db 63, 58, 47 ;
db 63, 63, 47 ; [orange]
db 59, 63, 47 ;
db 55, 63, 47 ; [yellow]
db 47, 63, 49 ;
db 47, 63, 58 ; [green]
db 47, 62, 63 ;
db 47, 57, 63 ; [cyan]
db 47, 50, 63 ;
db 51, 47, 63 ;
db 58, 47, 63 ; [violet]
db 63, 47, 57 ;color #15
db 15
test db 63, 63, 63 ;
db 33, 33, 33 ;
db 63, 63, 63 ;
db 33, 33, 33 ;
db 63, 63, 63 ;
db 33, 33, 33 ;
db 63, 63, 63 ;
db 63, 63, 63 ;
db 33, 33, 33 ;
db 63, 63, 63 ;
db 33, 33, 33 ;
db 63, 63, 63 ;
db 0, 0, 0 ;
db 0, 0, 0 ;
db 0, 0, 0 ;
db 12
cseg ends
public EMS30
public EMSerr
public EMShandle
public EMSname
public EndOfNonresident
public EndOfResident
public MaxLines
public MaxRev
public _mypsp
public ainmsg
public alllines
public aval
public blackcolor
public buffersize
public checkx
public checkxy
public cnvmsg
public colorset
public colorspeed
public colorwait
public counter
public curcolor
public cval
public de0
public de1
public deinstall
public delay
public demsg
public di1
public di2
public di4
public doline
public dox
public doxy
public drawmoire
public emmname
public ex1
public finddigit
public fire
public fontblocks
public freebuf
public frost
public getEMS
public getbuf
public getcoords
public gfxcopout
public gfxinstalled
public gfxmode
public gonow
public index
public inmsg
public int10hOK
public keybuff
public length
public linesx1
public linesx2
public linesy1
public linesy2
public main
public maxcolor
public mirror
public moire
public mouse
public mousesize
public msg
public newmsg
public newopts
public noEMS
public nomsg
public noresident
public nr1
public numsets
public nw1
public old08h
public old09h
public old10h
public old13h
public old17h
public oldmx
public oldmy
public onoff
public optaddr
public options
public our08h
public our09h
public our10h
public our13h
public our17h
public pastel
public rainbow
public randir
public randvel
public ranex
public rb20
public rd1
public reset
public revdir
public revex
public reznew
public rnd
public rndcnt
public rnum
public runthis
public rval
public sax
public sax2
public sbp
public sbx
public sbx2
public scs
public scx
public scx2
public sdi
public sds
public sds2
public sdx
public sdx2
public seed
public ses
public setEMS
public setblank
public setcolor
public setdelay
public setlines
public setminutes
public setmirror
public setmouse
public setoff
public seton
public setpages
public setsavfon
public setspeed
public setup
public setvidact
public sfl
public sip
public ssi
public stilmsg
public storetext
public suremsg
public switchdir
public textbuff
public timeout
public usage
public useEMS
public videomode
public wait
public x1
public x1rev
public x2
public x2rev
public xv1
public xv2
public y1
public y1rev
public y2
public y2rev
public yv1
public yv2
end main
;______ EOF ___________________________________________________________________